#include <pspkernel.h>
#include <pspiofilemgr.h>
#include <stdio.h>
#include <string.h>
#include "isoloader.h"

int CopyTextToFormatedText(const char* src, char* out, int max);
void UpDir(char* path);
void CheckPath(Directory* dirs, int j);

ISO* IsoLoad(SceUID fd){
	if(fd<0)return NULL;

	int levels[64] = { 0 };
	ISO* iso = (ISO*)geMalloc(sizeof(ISO));
	Directory* dirs = (Directory*)geMalloc(sizeof(Directory)*64);
	memset(dirs, 0, sizeof(Directory)*64);
	File* files = (File*)geMalloc(sizeof(File)*256);

	int i=0, j=0, k=0, a=0, len=0, nFiles=0, pos=0, size=0;
	char name[256], path[1024];
	char* buffer = (char*)geMalloc(sizeof(char)*4096);
	memset(buffer, 0, 4096);

	//Get CD Name
	sceIoLseek(fd, 0x8000, PSP_SEEK_SET);
	sceIoRead(fd, buffer, 128);
	CopyTextToFormatedText(strstr(buffer, "CD001")+7, iso->name, 128);

	//Get Dirs
	memset(buffer, 0, 4096);
	i = 0x9010;
	while(buffer[0]==0){
		sceIoLseek(fd, i, PSP_SEEK_SET);
		sceIoRead(fd, buffer, 1024);
		i += 0x0800;
	}
	for(i=0, j=0; i<1024;){
		memset(levels, 0, sizeof(int)*64);
		dirs[j].level = buffer[i];
		len = CopyTextToFormatedText(buffer+i+2, dirs[j].name, 256);
		CheckPath(dirs, j);
		i += (8 + len);
		for(i=i;((i<1024)&&(buffer[i]==0));i++);
		j++;
		if(buffer[i]+buffer[i+1]+buffer[i+2]+buffer[i+3]+buffer[i+4]+buffer[i+5]+buffer[i+6]+buffer[i+7]==0)break;
	}
	iso->dirs = dirs;
	iso->nDirs = j;

	//Get Files
	j = 0;
	k = 0xB010;
//	DebugPrint("Files list :\n");
	while(1){
		i = 0x70;
		pos = size = 0;
		sceIoLseek(fd, k, PSP_SEEK_SET);
		sceIoRead(fd, buffer, 1024);
		if(buffer[0]!=0x08)break;
		while(1){
			len = CopyTextToFormatedText(buffer+i+1, name, 256);
			for(a=(i+1+len); buffer[a]==0; a++);
			if(buffer[a]==0x0d){
				if(j>0){
					strcpy(path, dirs[j-1].path);
					strcat(path, name);
				}else{
					strcpy(path, "/");
					strcat(path, name);
				}
				pos = ((u8)buffer[i-30] | (u8)buffer[i-29]<<8 | (u8)buffer[i-28]<<16 | (u8)buffer[i-27]<<24) * 2048;
				size = ((u8)buffer[i-22] | (u8)buffer[i-21]<<8 | (u8)buffer[i-20]<<16 | (u8)buffer[i-19]<<24);
				files[nFiles].addr = pos;
				files[nFiles].size = size;
				files[nFiles].fd = ((int)name - size + (int)path);
				strcpy(files[nFiles].name, name);
				strcpy(files[nFiles].path, path);
//				DebugPrint(" \"%s\"\n", (int)files[nFiles].path);
				nFiles++;
			}else if((u8)buffer[a]==0x8d){
			}
			i += ((a-i)+42);
			if(buffer[i]+buffer[i+1]+buffer[i+2]+buffer[i+3]+buffer[i+4]+buffer[i+5]+buffer[i+6]+buffer[i+7]==0)break;
		}
		if(/*(k>=0xC9B0)||*/(j>iso->nDirs))break;

		k += 0x0800;
		j++;
	}
	iso->files = files;
	iso->nFiles = nFiles;
	geFree(buffer);
	return iso;
}

File* IsoGetFile(ISO* iso, const char* filename){
	int i = 0;
	for(i=0; i<iso->nFiles; i++){
		if(!strcmp(filename, iso->files[i].path)){
			return &iso->files[i];
		}
	}
	return (File*)0x80010002;
}

int GetParent(Directory* dirs, int j){
	return dirs[j].level-2;
}

void CheckPath(Directory* dirs, int j){
	char DIRS[256][64] = { "" };
	int i=j, parent=j, k=0;
	while(i>=0){
		i = parent;
		parent = GetParent(dirs, i);
		strcpy(DIRS[k], dirs[i].name);
		k++;
	}
	memset(dirs[j].path, 0, 1024);
	strcpy(dirs[j].path, "/");
	for(k=k-2; k>=0; k--){
		strcat(dirs[j].path, DIRS[k]);
		strcat(dirs[j].path, "/");
	}
}

void UpDir(char* path){
	int i = 0;
	for(i=strlen(path); i>=0; i--){
		if((i!=(int)strlen(path))&&(path[i]=='/'))break;
		path[i] = 0;
	}
}

int CopyTextToFormatedText(const char* src, char* out, int max){
	memset(out, 0, max);
	int i = 0;
	int len = 0;
	for(i=0; ((i<max)&&(i<(int)strlen(src))); i++){
		if((src[i]==0) || (src[i]<=0x07) || (src[i]==0x20 && src[i+1]==0x20 && src[i+2]==0x20 && src[i+3]==0x20)){
			break;
		}
		out[i] = src[i];
		len++;
	}
	return len;
}
